import { useReducer, createContext } from "react";
import EventBus from "./events";

type AnchorPos =
  | "left-top"
  | "top"
  | "right-top"
  | "left"
  | "right"
  | "left-bottom"
  | "bottom"
  | "right-bottom";

interface NodeProp {
  width: number;
  height: number;
  position: { x: number; y: number };
  fill?: string;
  text?: string;
  textColor?: string;
  anchor?: AnchorPos[];
  type: string;
  showAnchor?: boolean;
  href?: string;
}

interface Line {
  start: { x: number; y: number };
  end: { x: number; y: number };
}

interface JoinLineType {
  start: { nodeIndex: number; anchorPos: AnchorPos };
  end: { nodeIndex: number; anchorPos: AnchorPos };
}

interface InitState {
  nodes: NodeProp[];
  lines: JoinLineType[];
  assisitLine: Partial<Line>;
  containerInfo: {
    x?: number;
    y?: number;
    width?: number;
    height?: number;
  };
  currentNode: any;
}

export const initialState: InitState = {
  nodes: [],
  lines: [],
  assisitLine: {},
  containerInfo: {},
  currentNode: null,
};

const events = new EventBus();

const BaseContext = createContext({
  state: initialState,
  dispatch: (prop: { type: string; payload: any } | any) => {},
  events: events,
});

function reducer(state: InitState, action: any) {
  let copyData = Object.assign({}, state);
  const { type, payload } = action;
  switch (type) {
    case "containerInfo":
      copyData.containerInfo = payload;
      break;
    case "nodeChange":
      copyData.nodes[payload.index] = payload.newNode;
      break;
    case "drawAssistLine":
      copyData.assisitLine = payload;
      break;
    case "addJoinLine":
      copyData.lines.push(payload);
      break;
    case "addNode":
      copyData.nodes.push(payload);
      break;
    case "setCurrent":
      copyData.currentNode = payload;
      break;
    case "updateLines":
      copyData.lines = payload;
      break;
    case "deleteNode":
      let newNode = [...copyData.nodes];
      newNode.splice(payload, 1);
      copyData.nodes = newNode;
      break;
    case "loadFile":
      copyData = JSON.parse(payload);
      break;
    default:
      break;
  }
  return copyData;
}

export default function ContainerProvider(props: any) {
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <BaseContext.Provider value={{ state, dispatch, events }}>
      {props.children}
    </BaseContext.Provider>
  );
}

export type { NodeProp, Line, JoinLineType };
export { BaseContext };
